/**
 * Copyright (C) 2008 Mathieu Carbou <mathieu.carbou@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.mycila.maven.ui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import javax.swing.JFileChooser;
import javax.swing.JFrame;

import com.mycila.xmltool.XMLDoc;
import com.mycila.xmltool.XMLTag;

/**
 * @author Mathieu Carbou - mathieu.carbou(at)gmail.com
 */
public final class MavenDeployer {

    private static File currentDir = new File(".");
    private static Deployer deployer;
    private static File pom;

    public static void main(String[] args) {
        show();
    }

    public static void show() {
        final MavenDeployerGui gui = new MavenDeployerGui();
        final Chooser repositoryChooser = new Chooser(gui.formPanel, JFileChooser.DIRECTORIES_ONLY);
        final Chooser artifactChooser = new Chooser(gui.formPanel, JFileChooser.FILES_ONLY);
        final Chooser pomChooser = new Chooser(gui.formPanel, JFileChooser.FILES_ONLY, new POMFilter());

        gui.cancel.setEnabled(false);
        gui.cbDeployPOM.setVisible(false);
        gui.cbDeployPOM.setEnabled(false);
        gui.mavenBin.setText(findMavenExecutable());

        gui.textGAV.addFocusListener(new FocusListener() {

            @Override
            public void focusLost(FocusEvent e) {
                readPOMFromGav(gui);
            }

            @Override
            public void focusGained(FocusEvent e) {
                // Do nothing
            }
        });
        gui.repositoryBrowser.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                File repo = repositoryChooser.chooseFrom(currentDir);
                if (repo != null) {
                    currentDir = repositoryChooser.currentFolder;
                    gui.repositoryURL.setText(repo.getAbsolutePath());
                }
            }
        });

        gui.artifactBrowser.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                File artifact = artifactChooser.chooseFrom(currentDir);
                if (artifact != null) {
                    currentDir = artifactChooser.currentFolder;
                    gui.artifactFile.setText(artifact.getAbsolutePath());
                    guessGAV(gui);
                }
            }
        });

        gui.deploy.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                deployer = new Deployer(gui, pom, false);
                deployer.execute();
            }
        });
        gui.btnInstall.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                deployer = new Deployer(gui, pom, true);
                deployer.execute();
            }
        });

        gui.clear.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                gui.console.setText("");
            }
        });

        gui.cancel.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (deployer != null) {
                    deployer.stop();
                    deployer = null;
                }
            }
        });

        gui.cbDeployPOM.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                boolean enable = !gui.cbDeployPOM.isSelected();
                gui.groupId.setEnabled(enable);
                gui.artifactId.setEnabled(enable);
                gui.classifier.setEnabled(enable);
                gui.version.setEnabled(enable);
                gui.packaging.setEnabled(enable);
                gui.description.setEnabled(enable);
                readPOM(gui);
            }
        });

        gui.loadPOM.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                pom = pomChooser.chooseFrom(currentDir);
                if (pom != null) {
                    currentDir = pomChooser.currentFolder;
                    readPOM(gui);
                    gui.cbDeployPOM.setText("Deploy also " + pom.getAbsolutePath());
                    gui.cbDeployPOM.setEnabled(true);
                    gui.cbDeployPOM.setVisible(true);
                }
            }
        });

        JFrame frame = new JFrame("Maven Deployer 0.0.2 (Inhanced by BJH)" /*+ " - By Mathieu Carbou (http://blog.mycila.com)"*/);
        frame.setContentPane(gui.formPanel);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setLocationByPlatform(true);
        frame.pack();
        frame.setVisible(true);
    }

    protected static void guessGAV(MavenDeployerGui gui) {
        String artifactFileText = gui.artifactFile.getText();
        File artifactFile = new File(artifactFileText);
        if (!artifactFile.exists()) {
            return;
        }

        if (!artifactFile.getName().toLowerCase().endsWith(".jar")) {
            return;
        }
        boolean pomContained = false;

        try {
            JarFile jarFile = new JarFile(artifactFile);
            Enumeration<JarEntry> entries = jarFile.entries();
            while (entries.hasMoreElements()) {
                JarEntry jarEntry = entries.nextElement();
                if (!jarEntry.getName().toLowerCase().startsWith("meta-inf/maven")) {
                    continue;
                }
                if (jarEntry.getName().toLowerCase().endsWith("pom.xml")) {
                    System.out.println(jarEntry.getName());
                    InputStream is = jarFile.getInputStream(jarEntry);
                    readPOM(is, gui);
                    gui.textGAV.setText("<dependency>\r\n" +
                            "    <groupId>" + gui.groupId.getText() + "</groupId>\r\n" +
                            "    <artifactId>" + gui.artifactId.getText() + "</artifactId>\r\n" +
                            "    <version>" + gui.version.getText() + "</version>\r\n" +
                            "</dependency>");
                    pomContained = true;
                    break;
                }

                if (jarEntry.getName().toLowerCase().endsWith("pom.properties")) {
                    System.out.println(jarEntry.getName());
                    //break;
                }
            }
            if (!pomContained) {
                readPOMFromGav(gui);
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static String findMavenExecutable() {
        String script = "mvn";
        if (System.getProperty("os.name").toLowerCase().contains("windows")) {
            script += ".bat";
        }
        for (String path : System.getenv("PATH").split(File.pathSeparator)) {
            File file = new File(path, script);
            if (file.exists() && file.isFile() && file.canRead()) {
                return file.getAbsolutePath();
            }
        }
        return "";
    }

    private static void readPOM(InputStream is, MavenDeployerGui gui) {
        XMLTag doc = XMLDoc.from(is, true).gotoRoot();
        readPOM(doc, gui);
    }

    private static void readPOM(MavenDeployerGui gui) {
        XMLTag doc = XMLDoc.from(pom, true).gotoRoot();
        readPOM(doc, gui);
    }

    private static void readPOMFromGav(MavenDeployerGui gui) {
        if (gui.textGAV.getText().trim().length() > 0) {
            XMLTag doc = XMLDoc.from(gui.textGAV.getText(), true).gotoRoot();
            readPOM(doc, gui);
        }
    }

    private static void readPOM(XMLTag doc, MavenDeployerGui gui) {
        try {
            String ns = doc.getPefix("http://maven.apache.org/POM/4.0.0");
            if (ns.length() > 0) {
                ns += ":";
            }
            //  %1$s means that we take the first argument provided, refer: String.format
            if (doc.hasTag("%1$sgroupId", ns)) {
                gui.groupId.setText(doc.getText("%1$sgroupId", ns));
            }
            else {
                gui.groupId.setText("");
            }
            if (doc.hasTag("%1$sartifactId", ns)) {
                gui.artifactId.setText(doc.getText("%1$sartifactId", ns));
            }
            else {
                gui.artifactId.setText("");
            }
            if (doc.hasTag("%1$sversion", ns)) {
                gui.version.setText(doc.getText("%1$sversion", ns));
            }
            else {
                gui.version.setText("");
            }
            if (doc.hasTag("%1$spackaging", ns)) {
                gui.packaging.setSelectedItem(doc.getText("%1$spackaging", ns));
            }
            else {
                gui.packaging.setSelectedItem("jar");
            }
            if (doc.hasTag("%1$sdescription", ns)) {
                gui.description.setText(doc.getText("%1$sdescription", ns));
            }
            else {
                gui.description.setText("");
            }
            if (doc.hasTag("%1$sdistributionManagement/%1$srepository/%1$surl", ns)) {
                gui.repositoryURL.setText(doc.getText("%1$sdistributionManagement/%1$srepository/%1$surl", ns));
            }
            else {
                gui.repositoryURL.setText("");
            }
            if (doc.hasTag("%1$sdistributionManagement/%1$srepository/%1$sid", ns)) {
                gui.repositoryID.setText(doc.getText("%1$sdistributionManagement/%1$srepository/%1$sid", ns));
            }
            else {
                gui.repositoryID.setText("");
            }
        }
        catch (Exception ee) {
            gui.console.setText(ExceptionUtils.asText(ee));
        }
    }
}
